package grabber;

import jxl.write.WriteException;
import obj.Item;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.*;

/**
 * User: Vladimir
 * Date: 18.08.12 Time: 13:08
 */
public class GSMSetGrabber {

    public static final int TIMEOUT = 20000;
    public static List<String> filters = new ArrayList<String>();

    public static List<Accessory> accs = new ArrayList<Accessory>();
    public static List<Brand> brands = new ArrayList<Brand>();

    public static final String BASE_PATH = "G:/projects/webasyst/data/extramobi/";
    public static final String BASE_URL = "http://gsmset.ru/";

    static {
        filters.add("used");
        filters.add("class A");
        filters.add("P/ N");
        accs.add(new Accessory("Дисплеи", "21", "LCD-Ekrani-dlya-sotovih-telefonov-i-KPK/", "disp"));
        accs.add(new Accessory("Тачскрины", "20", "Touchscreens-Tachskrini-dlya-sotovih-telefonov-i-KPK/", "touch"));
        accs.add(new Accessory("Шлейфы", "22", "Flat-Cable-SHleyfi/", "flatcable"));
        accs.add(new Accessory("Защитные пленки", "17", "Zashchitnie-plenki/", "plenki"));
        accs.add(new Accessory("Стилусы", "19", "Zashchitnie-plenki/", "stylus"));
        brands.add(new Brand("Samsung", "00"));
        brands.add(new Brand("Nokia", "01"));
        brands.add(new Brand("HTC", "03"));
        brands.add(new Brand("SonyEricsson", "se", "Sony Ericsson", "04"));
        brands.add(new Brand("BlackBerry", "06"));
        brands.add(new Brand("LG", "07"));
        brands.add(new Brand("Motorola", "08"));
    }

    public static void main(String[] args) throws IOException, InterruptedException, WriteException {
        for (Brand brand : brands) {
            for (Accessory acc : accs) {
                String path = BASE_PATH + acc.path + "/" + acc.path + "." + brand.fileName + ".xls";
                System.out.println(path);
                String url = BASE_URL + "brand/" + brand.name + "/" + acc.url;
                System.out.println(url);
                List<Model> models = parseModels(brand.name, url);

                int count = 1;
                List<Item> items = new ArrayList<Item>();
                for (Model model : models) {
                    String article;
                    if (count < 10) {
                        article = "00" + count;
                    } else if (count < 100) {
                        article = "0" + count;
                    } else {
                        article = "" + count;
                    }
                    Item item = new Item();
                    item.brand = brand.realName;
                    item.name = model.name.replace(brand.name, "");
                    item.article = acc.article + brand.article + article;
                    item.count = model.count;
                    item.price = model.price;
                    item.oldPrice = model.price;
                    System.out.println(model);
                    count++;
                    items.add(item);
                }
                Item.saveToXls(path, items);
            }
        }
    }

    private static List<Model> parseModels(String brand, String url) throws IOException, InterruptedException {
        Document document = Jsoup.connect(url).timeout(TIMEOUT).get();
        Elements elements = document.select("a.str_cataloga");
        int lastPageNum;
        try {
            String lastUrl = elements.get(elements.size() - 1).attr("href");
            lastPageNum = Integer.parseInt(lastUrl.substring(lastUrl.lastIndexOf("/") + 1, lastUrl.lastIndexOf(".")));
        } catch (ArrayIndexOutOfBoundsException e) {
            lastPageNum = 1;
        }

        Set<Model> models = new HashSet<Model>();
        System.out.println(lastPageNum);

        for (int page = 1; page <= lastPageNum; page++) {
            String pageUrl = url + page + ".html";
            System.out.println(pageUrl);
            while (true) {
                try {
                    document = Jsoup.connect(pageUrl).timeout(TIMEOUT).get();
                    break;
                } catch (SocketTimeoutException e) {
                    System.out.println("Reconnect...");
                    Thread.sleep(1000);
                }
            }
            Elements rows = document.select("table#tab_catalog tr");
            for (Element row : rows) {
                Elements cells = row.select("td");
                if (cells.size() < 1) {
                    continue;
                }
                int price;
                try {
                    price = Integer.parseInt(cells.get(3).text().split("\\s")[0]);
                } catch (NumberFormatException e) {
                    price = 0;
                } catch (IndexOutOfBoundsException e) {
                    break;
                }
                String name = cells.get(1).text();
                boolean orig = name.contains("ригин") || name.contains("rigin");
                int count = 0;
                String avail = cells.get(4).text();
                if (avail.lastIndexOf("нет в наличии") == -1 && avail.lastIndexOf("нет в наличии") == -1) {
                    count = 100;
                } else if (avail.lastIndexOf("нет в наличии") == 14 && avail.lastIndexOf("нет в наличии") == 14) {
                    count = 99;
                } else if (avail.lastIndexOf("нет в наличии") == 7 && avail.lastIndexOf("нет в наличии") == 27) {
                    count = 0;
                }
                name = filterName(name, filters);
                String[] fields = name.split("/");
                if (fields.length > 1) {
                    for (String modelName : fields) {
                        if (!modelName.startsWith(brand)) {
                            modelName = brand + " " + modelName.trim();
                        }
                        Model model = new Model();
                        model.name = modelName.trim();
                        model.orig = orig;
                        model.price = price;
                        model.count = count;
                        models.add(model);
                    }
                } else {
                    Model model = new Model();
                    model.name = name;
                    model.orig = orig;
                    model.price = price;
                    model.count = count;
                    models.add(model);
                }
                Thread.sleep(100);
            }
        }
        ArrayList<Model> sortedModels = new ArrayList<Model>(models);
        Collections.sort(sortedModels, new Model());
        return sortedModels;
    }

    private static String filterName(String name, List<String> filters) {
        for (String filter : filters) {
            name = name.replace(filter, "");
        }
        name = filterTextInBrackets(name);
        StringBuilder buffer = new StringBuilder();
        for (char c : name.toCharArray()) {
            if (legalCharacter(c)) {
                buffer.append(c);
            }
        }
        name = buffer.toString();
        name = name.replaceAll("\\s+", " ");
        return name.trim();
    }

    public static String filterTextInBrackets(String name) {
        while (true) {
            if (name.contains("(")) {
                int beginIndex = name.indexOf("(");
                int endIndex = name.indexOf(")") + 1;
                if (beginIndex > endIndex) {
                    name = name.replaceFirst("\\)", "");
                } else {
                    name = name.replace(name.substring(beginIndex, endIndex), "");
                }
            } else {
                return name;
            }
        }
    }

    private static boolean legalCharacter(char c) {
        String legalCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 /";
        return legalCharacters.contains(c + "");
    }
}

class Model implements Comparable<Model>, Comparator {
    String name;
    int price;
    int count;
    boolean orig;

    @Override
    public String toString() {
        return "Model{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", count=" + count +
                ", orig=" + orig +
                '}';
    }


    @Override
    public int compare(Object o1, Object o2) {
        return ((Model) o1).name.compareTo(((Model) o2).name);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Model model = (Model) o;

        if (name != null ? !name.equals(model.name) : model.name != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return name != null ? name.hashCode() : 0;
    }

    @Override
    public int compareTo(Model m) {
        return name.compareTo(m.name);
    }
}

class Accessory {
    String name;
    String article;
    String url;
    String path;

    Accessory(String name, String article, String url, String path) {
        this.name = name;
        this.article = article;
        this.url = url;
        this.path = path;
    }

}

class Brand {
    String name;
    String fileName;
    String realName;
    String article;

    Brand(String name, String article) {
        this.name = name;
        this.article = article;
        this.fileName = name.toLowerCase();
        this.realName = name;
    }

    Brand(String name, String fileName, String realName, String article) {
        this.name = name;
        this.article = article;
        this.realName = realName;
        this.fileName = fileName;
    }
}